package com.pai4j.zwiki.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.pai4j.zwiki.domain.entity.CodeStructureEntity;
import com.pai4j.zwiki.repository.CodeStructureRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Stream;

/**
 * 代码分析服务
 * 使用JavaParser解析Java代码结构
 *
 * @author pai4j
 * @since 2025-10-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CodeAnalysisService {

    private final CodeStructureRepository codeStructureRepository;
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final JavaParser javaParser = new JavaParser();

    /**
     * 分析项目代码结构
     *
     * @param workspacePath 项目工作目录
     * @param taskId        任务ID
     * @return 分析结果统计
     */
    @Transactional
    public Map<String, Object> analyzeProject(String workspacePath, String taskId) {
        log.info("开始分析项目代码, 任务ID: {}, 路径: {}", taskId, workspacePath);

        Map<String, Object> statistics = new HashMap<>();
        List<CodeStructureEntity> structures = new ArrayList<>();

        try {
            Path projectPath = Paths.get(workspacePath);

            // 查找所有Java文件
            List<Path> javaFiles = findJavaFiles(projectPath);
            statistics.put("totalJavaFiles", javaFiles.size());
            statistics.put("totalFiles", countAllFiles(projectPath));
            statistics.put("totalLines", 0L);

            long totalLines = 0;
            Set<String> packages = new HashSet<>();
            int classCount = 0;
            int methodCount = 0;

            // 解析每个Java文件
            for (Path javaFile : javaFiles) {
                try {
                    ParseResult<CompilationUnit> parseResult = javaParser.parse(javaFile);

                    if (parseResult.isSuccessful() && parseResult.getResult().isPresent()) {
                        CompilationUnit cu = parseResult.getResult().get();

                        // 提取包名
                        String packageName = cu.getPackageDeclaration()
                                .map(pd -> pd.getNameAsString())
                                .orElse("");
                        if (!packageName.isEmpty()) {
                            packages.add(packageName);
                        }

                        // 统计行数（使用try-with-resources确保流正确关闭）
                        long fileLines;
                        try (Stream<String> lines = Files.lines(javaFile)) {
                            fileLines = lines.count();
                        }
                        totalLines += fileLines;

                        // 解析类和接口（添加 null 检查）
                        cu.findAll(ClassOrInterfaceDeclaration.class).forEach(classDecl -> {
                            CodeStructureEntity classEntity = buildClassStructure(
                                    classDecl, taskId, packageName, javaFile, (int) fileLines);
                            if (classEntity != null) {
                                structures.add(classEntity);
                            }
                        });

                        classCount += cu.findAll(ClassOrInterfaceDeclaration.class).size();
                        methodCount += cu.findAll(MethodDeclaration.class).size();
                    }
                } catch (Exception e) {
                    log.warn("解析Java文件失败: {}", javaFile, e);
                }
            }

            statistics.put("totalLines", totalLines);
            statistics.put("packages", packages.size());
            statistics.put("classes", classCount);
            statistics.put("methods", methodCount);

            // 批量保存代码结构
            if (!structures.isEmpty()) {
                codeStructureRepository.saveAll(structures);
                log.info("保存了 {} 个代码结构", structures.size());
            }

            log.info("代码分析完成, 统计信息: {}", statistics);
            return statistics;

        } catch (IOException e) {
            log.error("分析项目代码失败", e);
            throw new RuntimeException("分析项目代码失败: " + e.getMessage(), e);
        }
    }

    /**
     * 查找所有Java文件
     */
    private List<Path> findJavaFiles(Path rootPath) throws IOException {
        List<Path> javaFiles = new ArrayList<>();
        try (Stream<Path> paths = Files.walk(rootPath)) {
            paths.filter(Files::isRegularFile)
                    .filter(p -> p.toString().endsWith(".java"))
                    .filter(p -> !p.toString().contains("/test/"))  // 排除测试目录
                    .filter(p -> !p.toString().contains("/target/")) // 排除编译目录
                    .forEach(javaFiles::add);
        }
        return javaFiles;
    }

    /**
     * 统计所有文件数量
     */
    private int countAllFiles(Path rootPath) throws IOException {
        try (Stream<Path> paths = Files.walk(rootPath)) {
            return (int) paths.filter(Files::isRegularFile)
                    .filter(p -> !p.toString().contains("/.git/"))
                    .filter(p -> !p.toString().contains("/target/"))
                    .filter(p -> !p.toString().contains("/node_modules/"))
                    .count();
        }
    }

    /**
     * 构建类结构实体
     */
    private CodeStructureEntity buildClassStructure(
            ClassOrInterfaceDeclaration classDecl,
            String taskId,
            String packageName,
            Path filePath,
            int lineCount) {

        try {
            // 提取依赖关系（继承和实现的接口）
            List<String> dependencies = new ArrayList<>();
            classDecl.getExtendedTypes().forEach(ext -> dependencies.add(ext.getNameAsString()));
            classDecl.getImplementedTypes().forEach(impl -> dependencies.add(impl.getNameAsString()));

            // 提取注解
            List<String> annotations = new ArrayList<>();
            classDecl.getAnnotations().forEach(ann -> annotations.add(ann.getNameAsString()));

            return CodeStructureEntity.builder()
                    .taskId(taskId)
                    .structureType(classDecl.isInterface() ? "interface" : "class")
                    .name(classDecl.getNameAsString())
                    .qualifiedName(packageName.isEmpty() ? classDecl.getNameAsString() 
                            : packageName + "." + classDecl.getNameAsString())
                    .packageName(packageName)
                    .accessModifier(classDecl.getAccessSpecifier().asString())
                    .filePath(filePath.toString())
                    .lineCount(lineCount)
                    .annotations(toJson(annotations))
                    .dependencies(toJson(dependencies))
                    .build();
        } catch (Exception e) {
            log.warn("构建类结构实体失败: {}", classDecl.getNameAsString(), e);
            return null;
        }
    }

    /**
     * 将对象转为JSON字符串
     */
    private String toJson(Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            return "[]";
        }
    }
}

